package zemberek3.lexicon.lexgraph;

import zemberek3.lexicon.LexicalForm;
import zemberek3.lexicon.SuffixLexicalDefinitions;

import java.util.Set;

public class Morphotactics {

    SuffixLexicalDefinitions lexForms = new SuffixLexicalDefinitions();

    // Verb Root
    EmptyLexNode VERB_ROOT_VOWEL_END = new EmptyLexNode("VERB_ROOT_VOWEL_END", lexForms.Verb_Root_Empty);
    EmptyLexNode VERB_ROOT_NO_CAUS = new EmptyLexNode("VERB_ROOT_NO_CAUS", lexForms.Verb_Root_Empty);
    EmptyLexNode VERB_ROOT_DEGIL = new EmptyLexNode("VERB_ROOT_DEGIL", lexForms.Verb_Root_Empty);
    EmptyLexNode VERB_ROOT_YE = new EmptyLexNode("VERB_ROOT_YE", lexForms.Verb_Root_Empty);
    EmptyLexNode VERB_ROOT_YI = new EmptyLexNode("VERB_ROOT_YI", lexForms.Verb_Root_Empty);

    // Positive
    EmptyLexNode POS_DEFAULT = new EmptyLexNode("POS_DEFAULT", lexForms.Pos_Empty);
    EmptyLexNode POS_ROOT_YE = new EmptyLexNode("POS_ROOT_YE", lexForms.Pos_Empty);
    EmptyLexNode POS_ROOT_YI = new EmptyLexNode("POS_ROOT_YI", lexForms.Pos_Empty);

    // Negative
    EmptyLexNode NEG_MA = new EmptyLexNode("NEG_DEFAULT", lexForms.Neg_mA);
    EmptyLexNode NEG_M = new EmptyLexNode("NEG_DEFAULT", lexForms.Neg_m);

    // Verb to Verb derivatıon.
    DerivationLexNode V2V_CAUS_T = new DerivationLexNode("V2V_CAUS_T", lexForms.Verb2Verb_Empty);
    DerivationLexNode V2V_CAUS_TIR = new DerivationLexNode("V2V_CAUS_TIR", lexForms.Verb2Verb_Empty);
    DerivationLexNode V2V_PASS_IN = new DerivationLexNode("V2V_PASS_IN", lexForms.Verb2Verb_Empty);
    DerivationLexNode V2V_PASS_NIL = new DerivationLexNode("V2V_PASS_NIL", lexForms.Verb2Verb_Empty);
    DerivationLexNode V2V_PASS_INIL = new DerivationLexNode("V2V_PASS_NIL", lexForms.Verb2Verb_Empty);
    DerivationLexNode V2V_ABIL_YA = new DerivationLexNode("V2V_ABIL_YA", lexForms.Verb2Verb_Empty);
    DerivationLexNode V2V_ABIL_YABIL = new DerivationLexNode("V2V_ABIL_YABIL", lexForms.Verb2Verb_Empty);

    // Causative.
    LexNode CAUS_TIR = new LexNode("CAUS_TIR", lexForms.Caus_tIr);
    LexNode CAUS_AR = new LexNode("CAUS_AR", lexForms.Caus_tIr);
    LexNode CAUS_T = new LexNode("CAUS_T", lexForms.Caus_t);

    // Passive.
    LexNode PASS_IN = new LexNode("PASS_IN", lexForms.Pass_In);
    LexNode PASS_NIL = new LexNode("PASS_NIL", lexForms.Pass_nIl);
    LexNode PASS_INIL = new LexNode("PASS_INIL", lexForms.Pass_InIl);

    LexNode ABIL_YA = new LexNode("ABIL_YA", lexForms.Abil_yA);
    LexNode ABIL_YABIL = new LexNode("ABIL_YABIL", lexForms.Abil_yAbil);

    // Imperative
    LexNode IMP = new LexNode("IMP", lexForms.Imp_Empty);

    // Future
    LexNode FUT_YACAK = new LexNode("FUT_YACAK", lexForms.Fut_yAcAk);

    // Aorist
    LexNode AOR_IR = new LexNode("AOR_IR", lexForms.Aor_Ir);
    LexNode AOR_AR = new LexNode("AOR_AR", lexForms.Aor_Ar);
    LexNode AOR_Z = new LexNode("AOR_Z", lexForms.Aor_z);
    LexNode AOR_EMPTY = new LexNode("AOR_EMPTY", lexForms.Aor_Empty);

    // A1sg
    LexNode A1SG_YIM = new LexNode("A1SG_YIM", lexForms.A1sg_yIm, NodeType.TERMINAL);

    // For now use naive succession
    public void initialize() {

        VERB_ROOT_VOWEL_END.addOut( // ara-[]
                V2V_ABIL_YA,    // ara--[]-ya-ma--
                V2V_CAUS_T,     // ara--[]-t---
                V2V_PASS_NIL,   // ara--[]-nıl---
                POS_DEFAULT,    // ara--[]--
                NEG_M,          // ara--[m]-ıyor-
                NEG_MA          // ara--[ma]--
        );

        V2V_CAUS_T.addOut(
                CAUS_T          // ara---[t]---
        );

        CAUS_T.addOut(
                V2V_PASS_NIL,   // ara---t-[]-ıl---
                V2V_CAUS_TIR,   // ara---t-[]-tır---
                V2V_ABIL_YA,    // ara---t-[]-a-ma--
                POS_DEFAULT,    // ara---t-[]---
                NEG_M,          // ara---t-[m]-ıyor--
                NEG_MA          // ara---t-[ma]--
        );

        V2V_ABIL_YA.addOut(
                ABIL_YA         // ara---[ya]-ma--
        );

        ABIL_YA.addOut(
                NEG_M,    // gel---e-[m]-iyor-
                NEG_MA    // gel---e-[me]-yebil-ir-
        );

        NEG_MA.addOut(
                IMP,           // gel-me-[]-
                FUT_YACAK,     // gel-me-[yecek]-
                V2V_ABIL_YABIL // gel-me-[]-yebil-ir-
        );

        FUT_YACAK.addOut(
                A1SG_YIM
        );

    }

    public static class PartialGraph {
        public final String id;
        private Set<LexNode> allNodes;
        public final LexNode root;

        public PartialGraph(String id, LexicalForm root) {
            this.id = id;
            this.root = makeNode(root);
        }

        LexNode makeNode(LexicalForm form) {
            return new LexNode(form.id + "_" + id, form);
        }

        LexNode makeNode(LexicalForm form, String name) {
            return new LexNode(form.id + "_" + name + "_" + id, form);
        }
    }


}
